package cshi.common;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Optional;


/**
 * Created by shichen on 2017/12/8.
 */

class Demo {
    public Demo() {

    }
    public Demo(String name){
        this.name=name;
    }

    String getName() {
        return name;
    }

    void setName(String n) {
        this.name = n;
    }
    private String name;
}

interface fruit {
    public abstract void eat();
}

class Apple implements fruit {
    @Override
    public void eat() {
        System.out.println("apple");
    }
}

class Orange implements fruit {
    @Override
    public void eat() {
        System.out.println("oragne");
    }
}

//利用反射来创建工厂，要比各种if/else方便！
//如果不知道类的全名，可以采用Property文件的方式将类的常用名(key)和类的全名绑定在一块，用户只需给出key
class Factory {
    public static fruit createFruit(String name) {
        fruit f = null;
        try {
            f = (fruit)Class.forName(name).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return f;
    }
}

public class Reflec  {
    public static void main(String[] args) throws Exception {
        Demo demo = new Demo();
        print(demo.getClass().getName());//获得完整的包名和类名
        Class<?> demo1 = null;
        Class<?> demo2 = null;
        Class<?> demo3 = null;
        //这三种方式都是来获取Class实例
        demo1 = Class.forName("cshi.common.Demo");
        demo2 = new Demo().getClass();
        demo3 = Demo.class;
        print(demo1.getName() + "," + demo2.getName());

        //将Class转化为具体的类，得保证有合适的构造函数
        Demo p = null;
        p = (Demo)demo1.newInstance();
        p.setName("cs");
        print(p.getName());


        //通过获取Construtor来构造
        Constructor<?> ctors[] = demo1.getConstructors();//取得全部的构造函数
        Demo d2 = (Demo)ctors[1].newInstance("cshi");//注意索引的顺序与构造方法声明的顺序一样

        Class<?> intf[] = demo1.getInterfaces();//获取demo1代表的类所继承的所有接口
        Optional<Class<?>> superClass = Optional.of(demo1.getSuperclass());
        if (!superClass.isPresent()) {
            print(demo1.getName() + " has no superclass");
        }else {
            print("super class is:" + superClass.get().getName());
        }

        Constructor<String> ctor = String.class.getConstructor(char[].class);
        String string = ctor.newInstance(new char[]{'a','b'});
        print(string);

        Method method[] = demo1.getMethods();//获得类的方法

        //AppClassLoader 加载classpath指定的类，是最常用的加载器。同时也是java中默认的加载器
        print("class loader:" + demo.getClass().getClassLoader().getClass().getName());
    }

    public static void print(Object object) {
        System.out.println(object);
    }
}
